﻿/*
 *  This file is part of SXAPI.
 *
 *  SXAPI is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, version 3 of the License.

 *  SXAPI is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with SXAPI.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Globalization;
using System.Security.Permissions;

namespace StackExchangeApi
{
    /// <summary>
    /// Occurs when a SearchQuery is constructed with
    /// constraints that are mutually exclusive.
    /// </summary>
    [Serializable]
    public sealed class IncompatibleSearchConstraintsException : Exception
    {
        /// <summary>
        /// Constructs a new IncompatibleSearchConstraintsException
        /// </summary>
        internal IncompatibleSearchConstraintsException() : base("The specific constraints are incompatible with this operation") { }

        /// <summary>
        /// Constructs a new IncompatibleSearchConstraintsException
        /// </summary>
        /// <param name="p1">One of the incompatible constraints</param>
        /// <param name="p2">The other incompatible constraint</param>
        internal IncompatibleSearchConstraintsException(SearchConstraint p1, SearchConstraint p2) :
            base(
             String.Format(
             CultureInfo.InvariantCulture,
             "{0} is not compatible with {1}",
             p1.GetType().Name, 
             p2.GetType().Name)) { }

        /// <summary>
        /// For serialization purposes
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        private IncompatibleSearchConstraintsException(SerializationInfo info, StreamingContext context)
            : base(info, context) { }

        /// <summary>
        /// Custom implementation of GetObjectData
        /// </summary>
        /// <param name="info">Populated with new properties</param>
        /// <param name="context">Streaming context</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }

    /// <summary>
    /// Occurs when SXAPI is exercised without first
    /// initializing it via SXAPI.Initialize(...)
    /// </summary>
    [Serializable]
    public sealed class NotInitializedException : Exception
    {
        /// <summary>
        /// For serialization purposes.
        /// 
        /// Do not use.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        private NotInitializedException(SerializationInfo info, StreamingContext context)
            : base(info, context) { }

        /// <summary>
        /// Construct a new NotInitializedException
        /// </summary>
        internal NotInitializedException() : base("Call SXAPI.Initialize(...) before using SXAPI") { }

        /// <summary>
        /// Custom implementation of GetObjectData
        /// </summary>
        /// <param name="info">Populated with new properties</param>
        /// <param name="context">Streaming context</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }

    /// <summary>
    /// Occurs when a SXAPI resource is initialized twice.
    /// </summary>
    [Serializable]
    public sealed class DoubleInitializationException : Exception
    {
        /// <summary>
        /// For serialization purposes.
        /// 
        /// Do not use.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        private DoubleInitializationException(SerializationInfo info, StreamingContext context)
            : base(info, context) { }

        /// <summary>
        /// Construct a new DoubleInitializationException
        /// </summary>
        internal DoubleInitializationException() : base() { }

        /// <summary>
        /// Custom implementation of GetObjectData
        /// </summary>
        /// <param name="info">Populated with new properties</param>
        /// <param name="context">Streaming context</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }

    /// <summary>
    /// Wrapper Exception for errors that occur when
    /// fetching data from a "Trilogy Site".
    /// </summary>
    [Serializable]
    public sealed class TrilogySiteDownloadException : Exception
    {
        /// <summary>
        /// The Uri that was unavailable or otherwise
        /// generated an error.
        /// </summary>
        public Uri CausingRequest { get; private set; }

        /// <summary>
        /// The Site the request was on.
        /// </summary>
        public StackExchangeSite Site { get; private set; }

        /// <summary>
        /// For serialization purposes.
        /// 
        /// Do not use.
        /// </summary>
        internal TrilogySiteDownloadException() { }

        /// <summary>
        /// For serialization purposes.
        /// 
        /// Do not use.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        private TrilogySiteDownloadException(SerializationInfo info, StreamingContext context) : base(info, context) { }

        /// <summary>
        /// Minimally functional TrilogySiteDownloadException
        /// 
        /// Do not use.
        /// </summary>
        /// <param name="message">Cause of the exception</param>
        internal TrilogySiteDownloadException(String message) : base(message) { }

        /// <summary>
        /// Minimally functional TrilogySiteDownloadException
        /// 
        /// Do not use
        /// </summary>
        /// <param name="message">The uri, as a string, that caused this exception</param>
        /// <param name="cause">The inner exception</param>
        internal TrilogySiteDownloadException(String message, Exception cause) : this(new Uri(message), cause) { }

        /// <summary>
        /// Construct a new TrilogySiteDownloadException
        /// </summary>
        /// <param name="request">The underlying request</param>
        /// <param name="cause">The inner exception</param>
        internal TrilogySiteDownloadException(Uri request, Exception cause) : base(String.Format(CultureInfo.InvariantCulture, "Failure getting: {0}", request), cause)
        {
            CausingRequest = request;
            Site = Utils.GetSiteForAddress(request.Host);
        }

        /// <summary>
        /// Custom implementation of GetObjectData
        /// </summary>
        /// <param name="info">Populated with new properties</param>
        /// <param name="context">Streaming context</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }
}
